home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / START.ASM < prev    next >
Assembly Source File  |  1988-06-02  |  24KB  |  938 lines

  1. PAGE    ,80
  2. ;
  3. TITLE * START.ASM *
  4. SUBTTL Program to start processes at a predetermined time.
  5. ;
  6. ;    CREATED    06-DEC-85    :RICHARD B JOHNSON
  7. ;
  8. IF1
  9. %OUT [PASS1]
  10. ELSE
  11. %OUT [PASS2]
  12. ENDIF
  13. ;
  14. ; Misc equates.
  15. ;
  16. CR        EQU    0DH
  17. LF        EQU    0AH
  18. MS_DOS        EQU    21H        ;SYSTEM
  19. CLK        EQU    1CH        ;TIMER VECTOR
  20. CLX        EQU    08H        ;BEGINNING OF TIMER VECTOR
  21. INT_BASE    EQU    20H        ;INTERRUPT CONTROLLER
  22. VID_ROM        EQU    10H        ;VIDEO ROM
  23. K        EQU    1024
  24. K16        EQU    16 * K
  25. CMD_BUF        EQU    80H        ;COMMAND LINE
  26. RAM        EQU    12H        ;GET AVAILABLE RAM
  27. MAX_HRS        EQU    23
  28. MAX_MIN        EQU    59
  29. MAX_SEC        EQU    MAX_MIN
  30. EQUIP        EQU    410H        ;EQUIPMENT FLAG
  31. BWSEG        EQU    0B000H        ;SEGMENT FOR BLACK/WHITR
  32. COSEG        EQU    0B800H        ;SEGMENT FOR COLOR
  33. ;
  34. ;
  35. PSEG    SEGMENT
  36.     ASSUME    CS:PSEG,SS:PSEG,DS:PSEG,ES:NOTHING
  37.     ORG    100H
  38. MAIN    PROC    NEAR
  39.     JMP    INIT
  40.     DB    'Copyright (C) 1985 Richard B. Johnson. '
  41.     DB    'All rights reserved. '
  42. PRP0    DB    CR,LF,'Process $'
  43. PRP1    DB    CR,LF,'will start at '
  44. HH    DB    '00:'
  45. MM    DB    '00:'
  46. SX    DB    '00. If not correct, hit any key.... $'
  47. PRP2    DB    ' aborted.',CR,LF,'$'
  48. PRP3    DB    ' loaded.',CR,LF,'$'
  49. PRP4    DB    CR,LF,'Usage:'
  50.     DB    CR,LF,'START HH:MM:SS \PATH\RUNFILE COMMAND STRING'
  51.     DB    CR,LF,LF,'Examples:'
  52.     DB    CR,LF,'START 23:55:00 C:\DOS\BACKUP.BAT TODAYS FILES'
  53.     DB    CR,LF,'START 12:00:00 \SETCLOCK'
  54.     DB    CR,LF,'START 15:00:00 COPY *.DAT E:'
  55.     DB    CR,LF,'$'
  56. PRP5:    DB    CR,LF,'The time entered must be LATER than the present '
  57.     DB    'time!',CR,LF,'$'
  58. ;
  59. BEEP    DB    7,'Your process will resume in a moment.'
  60.     DB    CR,LF,'$'
  61. ;
  62. ERRW    DB    CR,LF,'Not enough disk space to save the screen'
  63.     DB    CR,LF,'(need 16k).$'
  64. ;
  65. FILE1    DB    '\SCREEN.TMP',0
  66. FILEN    EQU    $ - FILE1
  67. FILE2    DB    '           ',0
  68. HANDLE    DW    ?
  69. ;
  70. CNT    DB    182            ;LOCAL CLOCK TICK COUNT
  71. SEC    DB    ?            ;LOCAL CLOCK SECONDS
  72. MIN    DB    ?            ;LOCAL CLOCK MINUTES
  73. HRS    DB    ?            ;LOCAL CLOCK HOURS
  74. SAV_SEC    DB    ?            ;COMMAND STRING SECS (BINARY)
  75. SAV_MIN    DB    ?            ;COMMAND STRING MINS (BINARY)
  76. SAV_HRS    DB    ?            ;COMMAND STRING HRS (BINARY)
  77. SS_SAV    DW    ?            ;USER'S STACK SEGMENT
  78. SP_SAV    DW    ?            ;USER'S STACK POINTER
  79. COMMAND    DB    '\COMMAND.COM',0
  80. ;
  81. BLOCK    DW    0            ;PARAMETER BLOCK FOR EXEC
  82.     DW    CMD_BUF            ;DEFALUT BUFFER
  83. BP_1    DW    ?            ;CS WRITTEN HERE
  84.     DW    5CH            ;DEFAULT FCB
  85. BP_2    DW    ?            ;CS WRITTEN HERE
  86.     DW    6CH            ;OTHER FCB
  87. BP_3    DW    ?            ;CS WRITTEN HERE
  88. ;
  89. DTA_SEG    DW    ?            ;USER'S DTA (SEGMENT)
  90. DTA_OFF    DW    ?            ;USER'S DTA (OFFSET)
  91. SSP_SAV    DW    ?            ;OUR STACK POINTER
  92. SAV_SEG    DW    ?            ;OLD INTERRUPT SEGMENT
  93. SAV_OFF    DW    ?            ;OLD INTERRUPT OFFSET
  94. CUR_SAV    DW    ?            ;CURSOR SAVE
  95. CUR_TYP    DW    ?            ;CURSOR TYPE
  96. CUR_PGE    DB    ?            ;CURRENT PAGE
  97. OLD_CLK    LABEL    DWORD            ;OLD TIMER VECTOR
  98. IP_CLK    DW    ?            ;IP FOR OLD CLOCK
  99. CS_CLK    DW    ?            ;CS FOR OLD CLOCK
  100. OLD_CLX    LABEL    DWORD            ;START OF CLOCK VECT
  101. IP_CLX    DW    ?            ;IP FOR START
  102. CS_CLX    DW    ?            ;CS FOR START
  103. CRT_FLG    LABEL    DWORD            ;CRITICAL FLAG (DOS)
  104. DOS_FLG    DW    ?            ;CRITICAL FLAG ADDRESS
  105.     DW    ?
  106. SEGMNT    DW    ?            ;VIDEO SEGMENT
  107. HERE    DB    0            ;REENTRY FLAG
  108. DISK    DB    ?            ;CURRENT DISK
  109. DIRZ    DB    '\'
  110. DIRECT    DB    64 DUP (?)        ;CURRENT DIRECTORY
  111. ;
  112. INFORM    DB    ' /C '
  113. BUFFER    DB    ' '            ;THE SPACE
  114. ASC_HRS    DB    'HH:'            ;HOURS IN ASCII
  115. ASC_MIN    DB    'MM:'            ;MINUTES IN ASCII
  116. NEW_CMD    EQU    $ - 2            ;NEW COMMAND LINE
  117. NEW_TXT    EQU    NEW_CMD + 1        ;WHERE TEXT STARTS
  118. ASC_SEC    DB    'SS'            ;SECONDS IN ASCII
  119. DELIM    DB    ' '            ;NORMAL SPACE
  120.     DB    64 DUP (?)        ;REST OF COMMAND LINE
  121. LINE    DB    CR,LF,'Batch '
  122. TIME    DB    '00:00:00 '
  123. DATE    DB    '00-JAN-00 '
  124. LEN    EQU    $ - LINE
  125. LINEBUF    DB    64 DUP (0)
  126. MONTH    DB    'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'
  127. LOGF    DB    '\BATCH.LOG',0        ;PROCESS LOG FILE
  128. LOGCHAN    DW    ?
  129. BYTES    DW    ?
  130. ;
  131. EVEN
  132.     DB    32 DUP ('STACK   ')
  133. STK_TOP    LABEL    WORD
  134. ;
  135. INIT:    MOV    AX,CS
  136.     MOV    WORD PTR [BP_1],AX    ;FOR 'LOAD AND EXECUTE'
  137.     MOV    WORD PTR [BP_2],AX
  138.     MOV    WORD PTR [BP_3],AX
  139.     CALL    SET_TIM            ;SET PRIVATE TIME
  140. ;
  141. ; Check for graphics board
  142. ;
  143.     PUSH    DS            ;SAVE DATA SEG
  144.     XOR    AX,AX            ;ZERO IT
  145.     MOV    DS,AX
  146.     MOV    AL,BYTE PTR DS:[EQUIP]    ;GET EQUIPMENT FLAG
  147.     POP    DS            ;RESTORE DATA SEGMENT
  148.     AND    AL,00110000B        ;MASK TRASH
  149.     MOV    WORD PTR [SEGMNT],BWSEG    ;ASSUME SEGMENT FOR B/W
  150.     CMP    AL,00110000B        ;IS IT BLACK AND WHITE?
  151.     JZ    SEG_OK            ;YES
  152.     MOV    WORD PTR [SEGMNT],COSEG    ;MUST BE  COLOR
  153. ;
  154. SEG_OK:    CALL    PARSE            ;PARSE COMMAND LINE
  155.     JC    FINIS            ;BAD COMMAND LINE
  156.     CALL    GET_FLAG        ;SET UP CRITICAL PROCESS FLAG
  157.     CALL    SET_INT            ;SET UP INTERRUPTS
  158.     CALL    SET_TIM            ;SET TIME AGAIN
  159.     CALL    KEEP3K
  160. KEEP:    MOV    AX,3100H        ;KEEP PROCESS FUNCTION
  161.     INT    MS_DOS
  162.     HLT                ;IN CASE SOMETHING'S BUSTED
  163.  
  164. FINIS:    MOV    AX,4C00H        ;TERMINATE PROCESS
  165.     INT    MS_DOS
  166. MAIN    ENDP
  167. ;
  168. CLK_INT    PROC    FAR
  169.     ASSUME    CS:PSEG,SS:PSEG,DS:PSEG,ES:NOTHING
  170.     PUSH    AX            ;SAVE
  171.     PUSH    DS            ;AND DS
  172.     PUSH    CS            ;COPY CODE SEGMENT
  173.     POP    DS            ;INTO DATA SEG
  174. ;
  175. ; We get interupted 18.2 times per second.
  176. ; Routine below produces 1 second 'Ticks' by
  177. ; dividing by 18.2 (honest). Subtracts 10 from 182
  178. ; each interupt and adds the remainder to 182 for
  179. ; the next run through the loop. Result is an AVERAGE
  180. ; division by 18.2.
  181.  
  182.     CMP    BYTE PTR [CNT],0FFH    ;FLAG SHOWS THAT WE TIMED OUT
  183.     JZ    BYPASS            ;ALREADY TIMED OUT
  184.     SUB    BYTE PTR [CNT],10    ;RUNNING COUNT
  185.     JNC    BYPASS            ;NO CARRY YET
  186.     ADD    BYTE PTR [CNT],182    ;CUTE EH?
  187. ;
  188. ; Simple 24 hour clock counter follows.
  189. ;
  190.     INC    BYTE PTR [SEC]        ;BUMP SECONDS COUNTER
  191.     CMP    BYTE PTR [SEC],60    ;ARE WE THERE YET?
  192.     JNZ    TIM_OK            ;NOPE
  193.     MOV    BYTE PTR [SEC],0    ;YES, ZERO SECONDS AND ....
  194.     INC    BYTE PTR [MIN]        ;BUMP MINUTES
  195.     CMP    BYTE PTR [MIN],60    ;ARE WE THERE YET?
  196.     JNZ    TIM_OK            ;NOPE
  197.     MOV    BYTE PTR [MIN],0    ;YES, ZERO MINUTES AND.... ETC
  198.     INC    BYTE PTR [HRS]
  199.     CMP    BYTE PTR [HRS],24
  200.     JNZ    TIM_OK
  201.     MOV    BYTE PTR [HRS],0
  202. ;
  203. ; Check new time against saved time from command line.
  204. ;
  205. TIM_OK:    MOV    AL,BYTE PTR [HRS]    ;GET HOURS
  206.     CMP    AL,BYTE PTR [SAV_HRS]    ;SAME AS SAVED?
  207.     JNZ    BYPASS            ;NO
  208.     MOV    AL,BYTE PTR [MIN]    ;GET MINUTES
  209.     CMP    AL,BYTE PTR [SAV_MIN]    ;SAME AS SAVED?
  210.     JNZ    BYPASS            ;NO
  211.     MOV    AL,BYTE PTR [SEC]    ;GET SECONDS
  212.     CMP    AL,BYTE PTR [SAV_SEC]    ;SAME AS SAVED?
  213.     JNZ    BYPASS            ;NO
  214.     MOV    BYTE PTR [CNT],0FFH    ;SET FLAG (WE ARE TIMED OUT)
  215. BYPASS:    POP    DS            ;OLD DATA SEG
  216.     POP    AX            ;AND AX
  217.     JMP    DWORD PTR CS:[OLD_CLK]    ;CHAIN TO NEXT (IF ANY)
  218. CLK_INT    ENDP
  219. ;
  220. ; This is the second clock interrupt vector.
  221. ;
  222. CLX_INT    PROC    FAR
  223.     CMP    BYTE PTR CS:[HERE],0    ;SEE IF REENTRY IS OCCURING
  224.     JNZ    HOME            ;YES, DON'T ALLOW REENTRY
  225.     CMP    BYTE PTR CS:[CNT],0FFH    ;SEE IF WE TIMED OUT
  226.     JNZ    HOME            ;NO, NOT YET
  227. ;
  228. ; Check to see if we interrupted something important.
  229. ;
  230.     PUSH    BX
  231.     PUSH    DS
  232.     LDS    BX,DWORD PTR CS:[CRT_FLG]    ;GET CRITICAL FLAG
  233.     CMP    BYTE PTR DS:[BX],0
  234.     POP    DS
  235.     POP    BX
  236.     JZ    TIMOUT            ;OK TO MAKE DOS CALLS 
  237. ;
  238. DONE:    MOV    BYTE PTR CS:[HERE],0    ;RESTORE REENTRY FLAG
  239. HOME:    JMP    DWORD PTR CS:[OLD_CLX]    ;CONTINUE
  240. ;
  241. ; Coast is clear, save stack and continue.
  242. ;
  243. TIMOUT:    MOV    BYTE PTR CS:[HERE],0FFH    ;SET ENTRY FLAG
  244.     PUSH    AX            ;SAVE USER'S
  245.     PUSH    DS            ;AND DS
  246.     PUSH    CS            ;COPY CODE SEGMENT
  247.     POP    DS            ;INTO DATA SEG
  248.     CLI
  249.     MOV    WORD PTR [SS_SAV],SS    ;SAVE IT
  250.     MOV    WORD PTR [SP_SAV],SP    ;SAVE STACK POINTER
  251.     MOV    AX,CS            ;GET CODE SEG
  252.     MOV    SS,AX            ;INTO STACK SEG
  253.     MOV    SP,OFFSET STK_TOP    ;LOCAL STACK
  254. ;
  255.     PUSH    BX            ;SAVE EVERYTHING IN LOCAL STACK
  256.     PUSH    CX
  257.     PUSH    DX
  258.     PUSH    DI
  259.     PUSH    SI
  260.     PUSH    BP
  261.     PUSH    ES
  262.     MOV    ES,AX            ;CODE SEGMENT INTO EXTRA SEG
  263. ;
  264. ; Run the program
  265. ;
  266. CODE    PROC    NEAR
  267.     CALL    RES_INT            ;RESTORE OLD INTERRUPT VECTORS
  268.     STI                ;OK TO INTERRUPT
  269.     CALL    RES_HRD            ;RESET HARDWARE CONTROLLER
  270.     CALL    SAV_SCR            ;SAVE THE USER'S SCREEN
  271.     CALL    TELL            ;TELL USER WHAT WE'RE DOING
  272.     CALL    LOG            ;LOG TO DISK
  273.     CALL    SAV_DIR            ;SAVE CURRENT DIRECTORY
  274.     CALL    SAV_DTA            ;SAVE USERS DATA AREA
  275.     CALL    SET_DTA            ;SET UP LOCAL DATA AREA
  276.     CALL    GET_MEM            ;GET MORE MEMORY (dummy)
  277.     JC    NOFREE            ;NOTHING AVAILABLE
  278.     MOV    ES,AX            ;NEW SEGMENT ADDRESS OF AVAILABLE MEM
  279. NOFREE:    CALL    KEEP3K            ;RESTORE TO POOL
  280.     CALL    RUN_PG            ;LOAD/EXECUTE COMMAND.COM
  281.     CALL    RES_DTA            ;RESTORE USERS DATA TRANSFER AREA
  282.     CALL    RES_DIR            ;RESTORE CURRENT DIRECTORY
  283.     CALL    RES_SCR            ;RESTORE USER'S SCREEN
  284.     CALL    KEEP0K            ;GIVE UP ALL MEMORY
  285. CODE    ENDP
  286. ;
  287. ; Return to user program.
  288. ;
  289.     POP    ES            ;RESTORE USER'S REGISTERS
  290.     POP    BP            ;SAVED IN LOCAL STACK
  291.     POP    SI
  292.     POP    DI
  293.     POP    DX
  294.     POP    CX
  295.     POP    BX
  296. ;
  297.     CLI
  298.     MOV    SS,WORD PTR [SS_SAV]    ;GET SAVED STACK SEG
  299.     MOV    SP,WORD PTR [SP_SAV]    ;GET OLD STACK POINTER
  300.     POP    DS            ;RESTORE REGISTERS FROM USER'S STACK
  301.     POP    AX
  302.     STI                ;ALLOW INTERRUPTS
  303.     JMP    DONE            ;CONTINUE
  304. CLX_INT        ENDP
  305. ;
  306. GET_MEM    PROC    NEAR
  307.     MOV    BX,40000        ;ASK FOR EVERYTHING IN THE COMPUTER
  308.     MOV    AH,4AH
  309.     INT    MS_DOS
  310.     RET
  311. GET_MEM    ENDP
  312. ;
  313. SET_TIM    PROC    NEAR
  314.     MOV    AH,2CH            ;SET PRIVATE TIME
  315.     INT    MS_DOS
  316.     MOV    BYTE PTR [HRS],CH    ;SAVE TIME IN PRIVATE CLOCK
  317.     MOV    BYTE PTR [MIN],CL
  318.     MOV    BYTE PTR [SEC],DH
  319.     RET
  320. SET_TIM    ENDP
  321. ;
  322. SET_INT    PROC    NEAR
  323.     CLI
  324.     CLD                ;FOREWARD
  325.     PUSH    DS            ;SAVE SEGMENT
  326.     XOR    AX,AX            ;GET OLD INTERRUPT VECTOR
  327.     MOV    DS,AX            ;FIRST SEGMENT IN MEMORY
  328.     MOV    SI,(CLK * 4)        ;INTERRUPT ADDRESS
  329.     LODSW                ;GET OFFSET
  330.     MOV    WORD PTR CS:[IP_CLK],AX    ;SAVE IN OUR CODE SEGMENT DS IS BUSY
  331.     LODSW                ;GET SEGMENT
  332.     MOV    WORD PTR CS:[CS_CLK],AX    ;SAVE THAT TOO
  333. ;
  334.     MOV    SI,(CLX * 4)        ;INTERRUPT ADDRESS
  335.     LODSW                ;GET OFFSET
  336.     MOV    WORD PTR CS:[IP_CLX],AX    ;SAVE IN OUR CODE SEGMENT DS IS BUSY
  337.     LODSW                ;GET SEGMENT
  338.     MOV    WORD PTR CS:[CS_CLX],AX    ;SAVE THAT TOO
  339.     POP    DS            ;RESTORE OUR DATA SEG
  340. ;
  341.     PUSH    ES            ;SAVE SEGMENT
  342.     XOR    AX,AX            ;ZERO
  343.     MOV    ES,AX            ;ZERO THE SEGMENT
  344.     MOV    DI,(CLK * 4)        ;GET INTERRUPT ADDRESS
  345.     MOV    AX,OFFSET CLK_INT    ;GET PROGRAM COUNTER
  346.     STOSW                ;PATCH
  347.     MOV    AX,CS            ;GET CODE SEGMENT
  348.     STOSW
  349. ;
  350.     MOV    DI,(CLX * 4)        ;GET INTERRUPT ADDRESS
  351.     MOV    AX,OFFSET CLX_INT    ;GET PROGRAM COUNTER
  352.     STOSW                ;PATCH
  353.     MOV    AX,CS            ;GET CODE SEGMENT
  354.     STOSW
  355.     POP    ES
  356.     STI
  357.     RET
  358. SET_INT    ENDP
  359. ;
  360. ; Restore old clock vector(s).
  361. ;
  362. RES_INT    PROC    NEAR
  363.     CLD                ;FOREWARD
  364.     CLI                ;NO INTERRUPTS
  365.     PUSH    ES            ;SAVE SEGMENT
  366.     XOR    AX,AX            ;ZERO
  367.     MOV    ES,AX            ;ZERO THE SEGMENT
  368.     MOV    DI,(CLK * 4)        ;GET INTERRUPT ADDRESS
  369.     MOV    AX,WORD PTR [IP_CLK]    ;GET PROGRAM COUNTER
  370.     STOSW                ;PATCH
  371.     MOV    AX,WORD PTR [CS_CLK]    ;GET CODE SEGMENT
  372.     STOSW
  373. ;
  374.     MOV    DI,(CLX * 4)        ;GET INTERRUPT ADDRESS
  375.     MOV    AX,WORD PTR [IP_CLX]    ;GET PROGRAM COUNTER
  376.     STOSW                ;PATCH
  377.     MOV    AX,WORD PTR [CS_CLX]    ;GET CODE SEGMENT
  378.     STOSW
  379. ;
  380.     POP    ES            ;RESTORE SEGMENT
  381.     STI                ;ALLOW INTERRUPTS
  382.     RET
  383. RES_INT    ENDP
  384. ;
  385. GET_FLAG    PROC    NEAR        ;GET CRITICAL DOS FLAG
  386.     PUSH    ES            ;WILL RETURN IN ES SO SAVE
  387.     MOV    AH,34H            ;FUNCTION
  388.     INT    MS_DOS            ;DO IT
  389.     MOV    WORD PTR [DOS_FLG],BX    ;SAVE IP
  390.     MOV    WORD PTR DOS_FLG[2],ES    ;SAVE CS
  391.     POP    ES            ;RESTORE EXTRA
  392.     RET
  393. GET_FLAG    ENDP
  394. ;
  395. PARSE    PROC    NEAR
  396.     MOV    SI,CMD_BUF        ;POINT TO THE STRING
  397.     LODSB                ;GET BYTE FROM BUFFER
  398.     OR    AL,AL
  399.     JZ    BAD            ;NOTHING TYPED
  400.     CBW
  401.     MOV    CX,AX            ;USE AS COUNT
  402.     CALL    CASE            ;FORCE TO UPPER CASE
  403.     MOV    DI,SI            ;COPY FOR COMPARE
  404.     MOV    AL,' '            ;LOOK FOR A SPACE
  405.     REPZ    SCASB            ;GET BY SPACES
  406.     JCXZ    BAD            ;NO SPACE
  407.     MOV    AL,':'            ;DELIMITER _AFTER_ CHARACTER
  408.     CALL    GET_CHR            ;GET CHARS, CONV TO BINARY
  409.     JC    BAD            ;NO GOOD
  410.     CMP    AL,MAX_HRS        ;WITHIN RANGE?
  411.     JG    BAD            ;NOPE
  412.     MOV    BYTE PTR [SAV_HRS],AL    ;SAVE GOOD BINARY
  413.     MOV    AL,':'            ;NEXT DELIMITER
  414.     CALL    GET_CHR            ;GET CHARACTER(S)
  415.     JC    BAD            ;BAD CHARACTER(S)
  416.     CMP    AL,MAX_MIN        ;WITHIN RANGE?
  417.     JG    BAD            ;NOPE
  418.     MOV    BYTE PTR [SAV_MIN],AL    ;SAVE GOOD BINARY
  419.     MOV    AL,' '            ;LOOK FOR SPACE
  420.     CALL    GET_CHR            ;GET LAST CHARACTER(S)
  421.     JC    BAD            ;IS GOOD
  422.     CMP    AL,MAX_SEC        ;WITHIN RANGE?
  423.     JG    BAD            ;NO
  424.     MOV    BYTE PTR [SAV_SEC],AL    ;SAVE GOOD BINARY
  425.     JMP    SHORT CHKRES        ;NOW, CHECK RESULTS
  426. ;
  427. BAD:    MOV    DX,OFFSET PRP4        ;POINT TO USAGE
  428.     CALL    PROMPT            ;PRINT TO SCREEN
  429.     STC                ;SHOW ERROR
  430.     RET
  431. ;
  432. CHKRES:    CALL    CHK_TIM            ;SEE IF WE ENTERED TIME PROPERLY
  433.     JNC    TIMCHK            ;IT WAS OK
  434.     MOV    DX,OFFSET PRP5        ;POINT TO 'IMPROPER TIME'
  435.     CALL    PROMPT            ;PRINT
  436.     STC                ;SHOW ERROR
  437.     RET
  438. ;
  439. TIMCHK:    PUSH    SI            ;CHECK RESULTS
  440.     MOV    SI,OFFSET SAV_HRS    ;WHERE BINARY IS
  441.     MOV    DI,OFFSET HH        ;WHERE TO PUT ASCII
  442.     CALL    ASCIIM            ;DO IT
  443.     MOV    SI,OFFSET SAV_MIN    ;WHERE BINARY IS
  444.     MOV    DI,OFFSET MM        ;WHERE TO PUT ASCII
  445.     CALL    ASCIIM            ;DO IT
  446.     MOV    SI,OFFSET SAV_SEC    ;WHERE BINARY IS
  447.     MOV    DI,OFFSET SX        ;WHERE TO PUT ASCII
  448.     CALL    ASCIIM            ;DO IT
  449. ;
  450.     MOV    DX,OFFSET PRP0        ;POINT TO 'PROCESS'
  451.     CALL    PROMPT            ;PRINT TO SCREEN
  452. ;
  453.     MOV    DI,CMD_BUF        ;POINT TO COMMAND LINE
  454.     MOV    AL,CL            ;BYTE COUNT REMAINING
  455.     ADD    AL,3            ;BYTES FOR ' \C '
  456.     STOSB
  457.     PUSH    CX            ;SAVE PRESENT COUNT
  458.     MOV    CX,4            ;BYTES TO MOVE (TO WHERE TIME WAS)
  459.     MOV    SI,OFFSET INFORM    ;STRING TO MOVE
  460.     REP    MOVSB            ;MOVE INTO BUFFER
  461.     POP    CX            ;RESTORE COUNT
  462.     SUB    CX,2            ;NO LEADING SPACE OR CARRIAGE RETURN
  463.     POP    SI            ;GET SAVED STRING POINTER
  464.     INC    SI            ;GET BY SPACE
  465.     JCXZ    ABRT            ;NOTHING TO LOAD
  466. DISPL:    LODSB                ;GET BYTE
  467.     STOSB                ;SAVE IN START OF BUFFER
  468.     CALL    PCHR            ;OUTPUT TO SCREEN
  469.     LOOP    DISPL            ;UNTIL DONE
  470.     MOV    AL,CR            ;BUFFER TERMINATION
  471.     STOSB
  472. ;
  473.     MOV    DX,OFFSET PRP1        ;POINT TO 'IF NOT CORRECT..'
  474.     CALL    PROMPT            ;PRINT TO SCREEN
  475. ;
  476.     MOV    CX,1000H        ;TIMER
  477. WAIT0:    MOV    AH,06H            ;DIRECT CONSOLE INPUT
  478.     MOV    DL,0FFH            ;WE WANT A CHARACTER
  479.     INT    MS_DOS            ;FROM DOS
  480.     TEST    AL,AL            ;ANY CHARACTER?
  481.     JNZ    ABRT            ;YES, ABORT
  482.     TEST    CL,CL            ;NOPE, LOOK FOR CX = XX00
  483.     JNZ    NO_DIS            ;DON'T DISPLAY
  484.     MOV    AL,CH            ;GET HIGH BYTE
  485.     TEST    AL,11111000B        ;WITHIN RANGE YET?
  486.     JNZ    NO_DIS            ;NOPE, DON'T DISPLAY
  487.     AND    AL,00000111B        ;YES, MASK HIGH BITS
  488.     ADD    AL,'0'            ;CONVERT TO ASCII
  489.     CALL    PCHR            ;PRINT TO SCREEN
  490.     MOV    AL,' '            ;GET A SPACE
  491.     CALL    PCHR            ;PRINT IT TOO
  492. NO_DIS:    LOOP    WAIT0
  493. ;
  494.     MOV    DX,OFFSET PRP3        ;POINT TO 'LOADED'
  495.     CALL    PROMPT            ;PRINT TO SCREEN
  496.     XOR    AX,AX            ;NO CARRY
  497.     RET
  498. ;
  499. ABRT:    MOV    DX,OFFSET PRP2        ;POINT TO 'ABORTED'
  500.     CALL    PROMPT            ;PRINT TO SCREEN
  501.     STC
  502.     RET
  503. PARSE    ENDP
  504. ;
  505. CHK_TIM    PROC    NEAR
  506.     MOV    AL,BYTE PTR [SAV_HRS]    ;GET COMMAND INPUT HOURS
  507.     CMP    AL,BYTE PTR [HRS]    ;GET PRESENT HOURS
  508.     JZ    CHKMIN            ;HOURS ARE THE SAME
  509.     JMP    SHORT TIMBAD        ;CARRY WILL SHOW ERROR
  510. CHKMIN:    MOV    AL,BYTE PTR [SAV_MIN]    ;GET COMMAND INPUT MINUTES
  511.     CMP    AL,BYTE PTR [MIN]    ;GET PRESENT MINUTES
  512.     JZ    CHKSEC            ;IF THE SAME
  513.     JMP    SHORT TIMBAD        ;CARRY SET IF BAD
  514. CHKSEC:    MOV    AL,BYTE PTR [SAV_SEC]    ;GET COMMAND INPUT SECONDS
  515.     CMP    AL,BYTE PTR [SEC]    ;GET PRESENT SECONDS
  516. TIMBAD:    RET
  517. CHK_TIM    ENDP
  518. ;
  519. PCHR    PROC    NEAR            ;PRINT CHARACTER IN AL, USES AX,DX
  520.     MOV    DL,AL            ;INTO DL
  521.     MOV    AH,2            ;CONTROL BYTE
  522.     INT    MS_DOS            ;TO DOS
  523.     RET
  524. PCHR    ENDP
  525. ;
  526. TELL    PROC    NEAR
  527.     MOV    DX,OFFSET BEEP        ;PRINT A BEEP
  528. PROMPT    PROC    NEAR            ;PRINT STRING ADDRESSED BY DX
  529.     MOV    AH,9            ;FUNCTION
  530.     INT    MS_DOS            ;SYSTEM
  531.     RET
  532. PROMPT    ENDP
  533. TELL    ENDP
  534. ;
  535. GET_CHR    PROC    NEAR            ;GET CHARACTER [DI] POINTER 
  536.     PUSH    CX            ;SAVE FOR NOW
  537.     REPNZ    SCASB            ;GET BY DELIMITER
  538.     POP    BX            ;SAVED AS FIRST COUNT (CX)
  539.     JCXZ    BADENTRY        ;WERE NO DEMITERS
  540.     SUB    BX,CX            ;BX= BYTES FROM SPACE TO ':'
  541.     CMP    BX,2            ;WAS IT TWO BYTES?
  542.     PUSHF                ;SAVE ANSWER TO THAT QUESTION
  543.     DEC    DI            ;BACK TO 'FOUND' CHARACTER
  544.     MOV    SI,DI            ;INTO SOURCE INDEX
  545.     SUB    SI,BX            ;BACK UP TO FIRST BYTE
  546.     LODSB                ;GET BYTE
  547.     SUB    AL,'0'            ;ASCII BIAS
  548.     POPF                ;ARE WE THROUGH?
  549.     JNZ    ALLDUN
  550.     MOV    BL,10            ;MULTIPLIER
  551.     MUL    BL            ;TIMES TEN
  552.     MOV    AH,AL            ;SAVE FOR NOW
  553.     LODSB                ;GET NEXT BYTE IN STRING
  554.     SUB    AL,'0'            ;ASCII BIAS
  555.     ADD    AL,AH            ;ADD TOGETHER
  556. ALLDUN:    MOV    DI,SI            ;NEXT ADDRESS FOR COMPARE
  557.     INC    DI
  558.     INC    DI            ;GET PAST THE COLON
  559.     OR    AL,AL            ;CLEAR CARRY
  560.     RET                ;AL= BINARY FROM STRING
  561. BADENTRY:
  562.     STC                ;SHOW BAD
  563.     RET
  564. GET_CHR    ENDP
  565. ;
  566. CASE    PROC    NEAR
  567.     PUSH    SI            ;SAVE INDEX
  568.     PUSH    CX            ;AND COUNT
  569.     MOV    DI,SI            ;DEST SAME AS SOURCE
  570. CASE0:    LODSB                ;GET BYTE
  571.     CMP    AL,'z'            ;CHECK UPPER LIMIT
  572.     JG    NO_CVT            ;NOT A LOWER CASE LETTER
  573.     CMP    AL,'a'            ;CHECK LOWER LIMIT
  574.     JL    NO_CVT            ;NOT A LOWER CASE LETTER
  575.     AND    AL,95            ;MASK LOWER CASE BITS
  576. NO_CVT:    STOSB                ;SAVE IN STRING
  577.     LOOP    CASE0
  578.     POP    CX            ;RESTORE COUNT
  579.     POP    SI            ;AND INDEX
  580.     RET
  581. CASE    ENDP
  582. ;
  583. RUN_PG    PROC    NEAR            ;LOAD AND EXECUTE PROGRAM
  584.     MOV    WORD PTR [SSP_SAV],SP    ;SAVE STACK POINTER
  585.     MOV    AX,4B00H        ;RUN PROGRAM EXE CALL
  586.     MOV    BX,OFFSET BLOCK        ;POINT TO PARAMETER BLOCK
  587.     MOV    DX,OFFSET COMMAND    ;POINT TO FILENAME
  588.     INT    MS_DOS            ;DO IT
  589.     MOV    AX,CS            ;GET GODE SEGMENT
  590.     MOV    DS,AX            ;SEGMENT FIXUPS
  591.     MOV    ES,AX
  592.     MOV    SS,AX            ;FIX UP STACK SEGMENT
  593.     MOV    SP,WORD PTR [SSP_SAV]    ;RESTORE LOCAL STACK
  594.     RET
  595. RUN_PG    ENDP
  596. ;
  597. KEEP3K    PROC    NEAR
  598.     MOV    BX,OFFSET TOP        ;PARAGRAPHS TO KEEP 
  599.     MOV    CL,4            ;BITS TO SHIFT
  600.     SHR    BX,CL
  601.     INC    BX            ;ROUND UP
  602.     JMP    SHORT FRE_MEM        ;IMPLIED RETURN
  603. KEEP3K    ENDP
  604. ;
  605. KEEP0K    PROC    NEAR
  606.     XOR    BX,BX            ;NO PARAGRAPHS
  607. FRE_MEM    PROC    NEAR            ;FREE UP MEMORY (PARAS IN BX)
  608.     MOV    AH,4AH            ;FUNCTION
  609.     PUSH    ES            ;SAVE, GET'S DESTROYED
  610.     INT    MS_DOS            ;DO IT
  611.     POP    ES            ;RESTORE EXTRA
  612.     RET
  613. FRE_MEM    ENDP
  614. KEEP0K    ENDP                ;FALL THROUGH
  615. ;
  616. SAV_SCR    PROC    NEAR            ;SAVE ALL SCREEN PAGES BY BRUTE FORCE!
  617.     CALL    GET_CUR            ;SAVE CURSOR POSITION
  618.     CALL    CREATE            ;CREATE A SCREEN DATA FILE
  619.     CALL    WRITE            ;WRITE SCREEN DATA TO FILE
  620.     PUSHF                ;SAVE POSSIBLE ERROR ON THE WRITE
  621.     CALL    CLOSE            ;CLOSE THE FILE
  622.     CALL    CLR_SCR            ;CLEAR THE SCREEN
  623.     POPF                ;GET ERROR CODE FROM WRITE
  624.     JZ    SAV_OK            ;WAS ENOUGH SPACE
  625.     MOV    DX,OFFSET ERRW        ;POINT TO ERROR MESSAGE
  626.     CALL    PROMPT            ;PRINT TO SCREEN
  627. SAV_OK:    RET                ;THAT'LL DO IT
  628. SAV_SCR    ENDP
  629. ;
  630. GET_CUR    PROC    NEAR            ;GET CURSOR POSITION
  631.     MOV    AH,15            ;GET CURRENT STATE
  632.     INT    VID_ROM
  633.     XOR    BL,BL            ;PAGE RETURNS IN BH
  634.     MOV    BYTE PTR [CUR_PGE],BH    ;SAVE CURRENT PAGE
  635.     MOV    AH,3            ;FUNCTION
  636.     INT    VID_ROM            ;DO IT
  637.     MOV    WORD PTR [CUR_SAV],DX    ;SAVE CURSOR POSITION
  638.     MOV    WORD PTR [CUR_TYP],CX    ;SAVE CURSOR TYPE
  639.     RET
  640. GET_CUR    ENDP
  641. ;
  642. RES_SCR    PROC    NEAR            ;RESTORE SCREEN
  643.     CALL    SET_CUR            ;RESTORE OLD CURSOR POSITION
  644.     CALL    OPEN            ;OPEN THE SCREEN DATA FILE
  645.     CALL    READ            ;READ INTO SCREEN MEMORY
  646.     CALL    CLOSE            ;CLOSE THE FILE
  647.     CALL    DELETE            ;AND BLOW IT AWAY
  648.     RET
  649. RES_SCR    ENDP
  650. ;
  651. SET_CUR    PROC    NEAR            ;SET CURSOR TO SAVED POSITION
  652.     MOV    AL,BYTE PTR [CUR_PGE]    ;GET 'OLD' CURRENT PAGE
  653.     MOV    AH,5            ;SELECT PAGE FUNCTION
  654.     INT    VID_ROM            ;DO IT
  655.     MOV    AH,2            ;FUNCTION
  656.     MOV    BH,BYTE PTR [CUR_PGE]    ;PAGE
  657.     MOV    DX,WORD PTR [CUR_SAV]    ;GET OLD POSITION
  658.     INT    VID_ROM            ;DO IT
  659.     MOV    AH,1            ;SET CURSOR TYPE
  660.     MOV    CX,WORD PTR [CUR_TYP]    ;GET CURSOR TYPE
  661.     INT    VID_ROM
  662.     RET
  663. SET_CUR    ENDP
  664. ;
  665. CLR_SCR    PROC    NEAR            ;CLEAR THE SCREEN
  666.     MOV    AX,0600H        ;FUNCTION
  667.     XOR    CX,CX            ;TOP LEFT HAND CORNER
  668.     MOV    DX,244FH        ;BOTTOM RIGHT
  669.     MOV    BH,7            ;NORMAL ATTRIBUTE
  670.     INT    VID_ROM            ;DO IT
  671.     XOR    DX,DX            ;TOP LEFT CORNER
  672.     MOV    AH,2            ;SET CURSOR FUNCTION
  673.     MOV    BH,0            ;PAGE ZERO
  674.     INT    VID_ROM            ;SET THE CURSOR
  675.     MOV    AH,1            ;SET CURSOR TYPE
  676.     MOV    CX,0608H        ;START LINE 6, END LINE 
  677.     INT    VID_ROM
  678.     RET
  679. CLR_SCR    ENDP
  680. ;
  681. SAV_DTA    PROC    NEAR            ;SAVE USERS DTA
  682.     PUSH    ES            ;SAVE, SEGMENT IN RETURN
  683.     MOV    AH,2FH            ;GET PRESENT DTA
  684.     INT    MS_DOS            ;CALL DOS
  685.     MOV    WORD PTR [DTA_SEG],ES    ;SAVE PRESENT DTA SEGMENT
  686.     MOV    WORD PTR [DTA_OFF],BX    ;SAVE PRESENT DTA OFFSET
  687.     POP    ES            ;RESTORE SEGMENT
  688.     RET
  689. SAV_DTA    ENDP
  690. ;
  691. SET_DTA    PROC    NEAR            ;SET NEW DTA TO 'DEFAULT'
  692.     MOV    AH,1AH            ;FUNCTION
  693.     MOV    DX,CMD_BUF        ;DS:DX = 80H
  694.     INT    MS_DOS            ;DO IT
  695.     RET
  696. SET_DTA    ENDP
  697. ;
  698. RES_DTA    PROC    NEAR            ;RESTORE USER'S DTA
  699.     MOV    AH,1AH            ;FUNCTION
  700.     MOV    DX,WORD PTR [DTA_OFF]    ;GET OLD OFFSET
  701.     PUSH    DS            ;SAVE PRESENT DATA SEG
  702.     MOV    DS,WORD PTR [DTA_SEG]    ;NEW (OLD USER'S) DATA SEG
  703.     INT    MS_DOS            ;RESET TO OLD
  704.     POP    DS            ;RESTORE DATA SEG
  705.     RET
  706. RES_DTA    ENDP
  707. ;
  708. RES_HRD    PROC    NEAR            ;RESET HARDWARE CONTROLLER
  709.     MOV    CX,5            ;FIVE POSSIBLE INTERRUPTS
  710.     MOV    AL,20H            ;NON-SPECIFIC END OF INTERRUPT
  711. HRD:    OUT    INT_BASE,AL
  712.     LOOP    HRD
  713.     RET
  714. RES_HRD    ENDP
  715. ;
  716. SAV_DIR    PROC    NEAR
  717.     MOV    AH,19H            ;CURRENT DISK FUNCTION
  718.     INT    MS_DOS
  719.     MOV    BYTE PTR [DISK],AL    ;SAVE
  720. ;
  721.     MOV    AH,47H            ;GET DIRECTORY FUNCTION
  722.     MOV    SI,OFFSET DIRECT
  723.     MOV    DL,0            ;CURRENT DISK
  724.     INT    MS_DOS
  725.     RET
  726. SAV_DIR    ENDP
  727. ;
  728. RES_DIR    PROC    NEAR
  729.     MOV    AH,0EH            ;SELECT DISK FUNCTION
  730.     MOV    DL,BYTE PTR [DISK]    ;GET SAVED DRIVE
  731.     INT    MS_DOS            ;DO IT
  732.     MOV    AH,3BH            ;CHANGE DIRECTORY FUNCTION
  733.     MOV    DX,OFFSET DIRZ
  734.     INT    MS_DOS
  735.     RET
  736. RES_DIR    ENDP
  737. ;
  738. ;
  739. ; The following routines are used to save the screen data on a disk.
  740. ;
  741. COPY    PROC    NEAR            ;COPY FILE NAME, DOS KILLS IT!!!
  742.     MOV    SI,OFFSET FILE1        ;COPY FROM HERE
  743.     MOV    DI,OFFSET FILE2        ;PUT IT THERE
  744.     MOV    CX,FILEN        ;BYTES TO COPY
  745.     REP    MOVSB            ;DO IT
  746.     RET
  747. COPY    ENDP
  748. ;
  749. CREATE    PROC    NEAR
  750.     CALL    COPY
  751.     MOV    AH,3CH            ;MS DOS FUNCTION
  752.     MOV    DX,OFFSET FILE2        ;POINTER TO FILE NAME
  753.     XOR    CX,CX            ;NORMAL ATTRIBUTES
  754.     INT    MS_DOS            ;DO IT
  755.     MOV    WORD PTR [HANDLE],AX    ;SAVE HANDLE
  756.     RET
  757. CREATE    ENDP
  758. ;
  759. OPEN    PROC    NEAR
  760.     CALL    COPY            ;GET NEW COPY OF FILE NAME
  761.     MOV    AX,3D00H        ;OPEN FUNCTION FOR READING
  762.     MOV    DX,OFFSET FILE2        ;POINT TO FILE NAME
  763.     INT    MS_DOS
  764.     MOV    WORD PTR [HANDLE],AX    ;SAVE ACCESS WORD
  765.     RET
  766. OPEN    ENDP
  767. ;
  768. WRITE    PROC    NEAR
  769.     MOV    AH,40H            ;WRITE TO FILE FUNCTION
  770.     MOV    BX,WORD PTR [HANDLE]    ;GET OPEN FILE HANDLE
  771.     MOV    CX,K16            ;16 K TO WRITE
  772.     PUSH    DS            ;SAVE DATA SEG
  773.     MOV    DS,WORD PTR [SEGMNT]    ;GET SCREEN SEGMENT
  774.     XOR    DX,DX            ;START AT THE BOTTOM
  775.     INT    MS_DOS            ;WRITE IT
  776.     POP    DS            ;RESTORE SEGMENT
  777.     CMP    AX,K16            ;DID WE GET IT ALL?
  778.     RET
  779. WRITE    ENDP
  780. ;
  781. READ    PROC    NEAR
  782.     MOV    AH,3FH            ;READ FILE FUNCTION
  783.     MOV    BX,WORD PTR [HANDLE]    ;FILE ACCESS WORD
  784.     MOV    CX,K16            ;16 K TO READ INTO SCREEN
  785.     PUSH    DS            ;SAVE DATA SEGMENT
  786.     MOV    DS,WORD PTR [SEGMNT]    ;GET SCREEN SEGMENT
  787.     XOR    DX,DX            ;START AT THE BOTTOM
  788.     INT    MS_DOS            ;READ INTO SCREEN MEMORY
  789.     POP    DS            ;RESTORE
  790.     RET
  791. READ    ENDP
  792. ;
  793. CLOSE    PROC    NEAR            ;CLOSE THE SCREEN DATA FILE
  794.     MOV    AH,3EH            ;FUNCTION
  795.     MOV    BX,WORD PTR [HANDLE]    ;FILE ACCESS WORD
  796.     INT    MS_DOS            ;DO IT
  797.     RET
  798. CLOSE    ENDP
  799. ;
  800. DELETE    PROC    NEAR            ;DELETE SCREEN DATA FILE
  801.     CALL    COPY            ;GET FRESH COPY OF FILE NAME
  802.     MOV    AH,41H            ;DELETE FUNCTION
  803.     MOV    DX,OFFSET FILE2        ;POINT TO FILE NAME
  804.     INT    MS_DOS            ;BLOW IT AWAY
  805.     RET
  806. DELETE    ENDP
  807. ;
  808. ; The following routines log the operation to disk
  809. ;
  810. LOG    PROC    NEAR
  811.     CALL    OPEN_LOG
  812.     CALL    FIND_END
  813.     CALL    GET_TIME
  814.     CALL    GET_DATE
  815.     CALL    GET_PROC
  816.     CALL    WRITE_LOG
  817.     CALL    CLOSE_LOG
  818.     RET
  819. LOG    ENDP
  820. ;
  821. GET_TIME    PROC    NEAR
  822.     MOV    AH,2CH            ;GET TIME FUNCTION
  823.     INT    MS_DOS
  824.     MOV    DI,OFFSET TIME
  825.     MOV    AL,CH            ;HOURS TO AL
  826.     CALL    ASCII            ;CONV TO ASCII
  827.     INC    DI            ;GET BY ':'
  828.     MOV    AL,CL            ;MINUTES TO AL
  829.     CALL    ASCII            ;CONV TO ASCII
  830.     INC    DI            ;GET BY ':'
  831.     MOV    AL,DH            ;SECS TO AL
  832.     CALL    ASCII            ;CONVERT TO ASCII
  833.     RET
  834. GET_TIME    ENDP
  835. ;
  836. GET_DATE    PROC    NEAR
  837.     MOV    AH,2AH
  838.     INT    MS_DOS
  839.     PUSH    CX            ;SAVE YEAR
  840.     MOV    AL,DL            ;GET DAY
  841.     MOV    DI,OFFSET DATE
  842.     CALL    ASCII
  843.  
  844.     MOV    DI,OFFSET DATE[3]
  845.     MOV    AL,DH            ;GET MONTHS
  846.     DEC    AL            ;JAN IS NOW ZERO OFFSET
  847.     CBW                ;A WORD
  848.     MOV    CL,3            ;MULTIPLIER (THREE CHRS PER MONTH)
  849.     MUL    CL            ;CALC OFFSET
  850.     MOV    SI,OFFSET MONTH        ;POINT TO TABLE
  851.     ADD    SI,AX            ;NEW OFFSET
  852.     MOV    CX,3            ;CHRS TO MOVE
  853.     REP    MOVSB            ;DO IT
  854.     POP    CX
  855.     SUB    CX,1900            ;NORMALIZE
  856.     MOV    AL,CL
  857.     MOV    DI,OFFSET DATE[7]
  858.     CALL    ASCII
  859.     RET
  860. GET_DATE    ENDP
  861. ;
  862. GET_PROC    PROC    NEAR
  863.     MOV    WORD PTR [BYTES],0    ;BYTE COUNT
  864.     MOV    SI,CMD_BUF        ;POINT TO COMMAND LINE
  865.     MOV    DI,OFFSET LINEBUF    ;WHERE TO PUT THE STRING
  866.     LODSB                ;GET CHARACTERS TYPED
  867.     SUB    AL,3            ;SUBTRACT FOR ' /C'
  868.     CBW
  869.     MOV    CX,AX            ;BYTE COUNT
  870.     JCXZ    GETOUT            ;NOTHING TYPED
  871.     ADD    AX,LEN            ;PLUS THE TIME/DATE STAMP
  872.     MOV    WORD PTR [BYTES],AX    ;SAVE FOR FILE WRITE
  873.     ADD    SI,3            ;GET BY THE ' /C'
  874.     REP    MOVSB            ;MOVE THE STRING
  875. GETOUT:    RET
  876. GET_PROC    ENDP
  877. ;
  878. OPEN_LOG    PROC    NEAR
  879.     MOV    DX,OFFSET LOGF        ;POINT TO LOG FILE NAME
  880.     MOV    AX,3D02H        ;OPEN FOR R/W
  881.     XOR    CX,CX            ;NORMAL FILE
  882.     INT    MS_DOS
  883.     JNC    OPNGD            ;GOOD OPEN
  884.     MOV    AX,3C00H        ;CREATE THE FILE, NONE EXISTS
  885.     MOV    DX,OFFSET LOGF        ;POINT TO FILE NAME
  886.     XOR    CX,CX            ;NORMAL FILE
  887.     INT    MS_DOS
  888. OPNGD:    MOV    WORD PTR [LOGCHAN],AX    ;SAVE CHANNEL ACCESS WORD
  889.     RET
  890. OPEN_LOG    ENDP
  891. ;
  892. FIND_END    PROC    NEAR
  893.     MOV    AX,4202H        ;MOVE TO END PLUS OFFSET
  894.     XOR    CX,CX
  895.     MOV    DX,CX            ;NO OFFSET
  896.     MOV    BX,WORD PTR [LOGCHAN]    ;GET HANDLE
  897.     INT    MS_DOS            ;DO IT
  898.     RET
  899. FIND_END    ENDP
  900. ;
  901. WRITE_LOG    PROC    NEAR
  902.     MOV    AX,4000H        ;WRITE TO FILE
  903.     MOV    DX,OFFSET LINE        ;POINT TO THE STRING TO BE WRITTEN
  904.     MOV    BX,WORD PTR [LOGCHAN]    ;HANDLE
  905.     MOV    CX,WORD PTR [BYTES]    ;NOW MUCH TO WRITE
  906.     JCXZ    NOWRT
  907.     INT    MS_DOS
  908. NOWRT:    RET
  909. WRITE_LOG    ENDP
  910. ;
  911. CLOSE_LOG    PROC    NEAR
  912.     MOV    AX,3E00H        ;CLOSE FILE
  913.     MOV    BX,WORD PTR [LOGCHAN]    ;FILE ACCESS WORD
  914.     INT    MS_DOS
  915.     RET
  916. CLOSE_LOG    ENDP
  917. ;
  918. ASCIIM    PROC    NEAR            ;BINARY(M) TO ASCII
  919.     LODSB
  920. ASCII    PROC    NEAR            ;CONV BINARY IN AL TO ASCII [DI]
  921.     MOV    AH,'0'-1        ;ASCII BIAS
  922. SUBT:    INC    AH            ;TENS COUNTER
  923.     SUB    AL,10            ;SUBTRACT TENS
  924.     JNC    SUBT            ;CONTINUE
  925.     ADD    AL,(10 + '0')        ;ONE TOO MANY ADD BACK PLUS ASCII BIAS
  926.     XCHG    AH,AL            ;SWAP FOR STRING STORE
  927.     STOSW                ;DO IT
  928.     RET
  929. ASCII    ENDP
  930. ASCIIM    ENDP
  931. ;
  932. TOP    EQU    $
  933. IF1
  934. %OUT -------
  935. ENDIF
  936. PSEG    ENDS
  937.     END    MAIN
  938.